home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / cug233 / cprint.c < prev    next >
Text File  |  1987-06-30  |  7KB  |  222 lines

  1. /*
  2.     CPRINT, Print a (fairly) neat listing of a c program
  3.  
  4.     Programmed by Andrew L. Bender, M. D.
  5.     June 24, 1984 - Version 1.0
  6.     June 26, 1984 - Version 1.1
  7.         Fix some bugs in string processing
  8.     July 3, 1984 - Version 1.2
  9.         Allow for printer file device.
  10.         Count source statements
  11.  
  12.     Permission is hereby given to freely distribute this
  13.     program but it may not be sold.  This program may be
  14.     modified by anyone as long as this notice remains.
  15.     The purpose of this program was to test the CI86
  16.     optimizing c compiler.  It does a clean compilation
  17.     of this program which tests most features of the
  18.     c language as described by Kernighan and Ritchie in
  19.     their book "The C Programming Language."
  20.     CI-86 is a trademark of Computer Innovations,
  21.     Tinton Falls NJ for their implementation of the full
  22.     c programming language as described in Kernighan and 
  23.     Ritchie.
  24.  
  25.     The listing contains two columns on the left:
  26.         column 1 is the "nesting level" of compound
  27.         statements and column 2 is a rough idea of
  28.         what the line number will be.  It is actually
  29.         a count of "\n" characters.  The heading on
  30.         each page gives the name of the file being
  31.         printed and the date and time it was created.
  32.  
  33.     If braces, brackets or parenthesis are unbalanced
  34.     this will be reported at the end of the listing.
  35.     A complete syntactical analysis of the program
  36.     would require more effort but would be worth it as
  37.     an exercise of much value in learning the c language
  38.     because of the facility and fluency needed to write
  39.     such a checker.
  40.     A program checker "lint" is quite through in its
  41.     analysis of c programs and is available on most
  42.     UNIX systems.
  43. */
  44. #include "local.h"
  45. #define    LPP    58
  46. #define    TAB    3
  47. #define    CHPL    74
  48. /* LPP=lines per page
  49.         TAB = number of spaces to indent for a tab
  50.         CHPL = characters to print on each line (74 is very tight)
  51.             because the line and level count take up 8 columns
  52. */
  53. unsigned int hour,minute,second,month,day,year;
  54. int pagect, level, tabct, lines, stmnt, linect;
  55. typedef int void;
  56. typedef int boolean;
  57. struct regval { int ax, bx, cx, dx, si, di, ds, es; };
  58. struct regval callreg, retreg;
  59. unsigned char title[60];
  60. boolean comment, quote, squote, instrng;
  61. unsigned char lineimage[520];
  62. unsigned char fmt[]=
  63.     {"\fListing of file: %s      Catalogued on %d/%d/%d At %d:%02d:%02d\
  64.            Page  %d \n\n"};
  65. unsigned char output[60]={"PRN:"};
  66.  
  67. /* top of page routine */
  68.  
  69. void toppage(pr)
  70. FILE *pr;
  71. {
  72.     fprintf(pr,fmt,title,month,day,year,hour,minute,second,pagect);
  73.     linect=1;
  74.     pagect++;
  75. }
  76.  
  77. /* main program */
  78.  
  79. main(argc,argv)
  80. int argc;
  81. unsigned char *argv[];
  82. {
  83.     int i,j,kk,jj,n;
  84.     unsigned char buf[600], fname [254];
  85.     unsigned char k;
  86.     int *pb;
  87.     int lbrace, rbrace, lparen, rparen, lbrack, rbrack;
  88.     extern FILE *fopen();
  89.     extern FILE *fclose();
  90.     extern char *fgets();
  91.     FILE *prn, *fd;
  92.     fprintf(stderr,"C Program Listing Version 1.2\n");
  93.     if (argc<2)
  94.         {
  95.         fprintf(stderr,"Type In Filename To Print: ");
  96.         gets(buf,254,stdin);    /*get user file name if not on control card*/
  97.         pb=index(buf,'\n');
  98.         *pb='\0';
  99.         }
  100.     else strcpy(buf,argv[1]);    /*copy control stmnt string to user bfr*/
  101.     makefnam(buf,".c",fname);    /*convert file name to filename.c*/
  102.     fprintf(stderr,"Listing Of File: %s \n",fname);
  103.     if (argc==3) strcpy(output,argv[2]);    /*copy prt file name to output*/
  104.     prn=fopen(output,"w");    /*open printer*/
  105.     if(prn==NULL) {
  106.         fprintf(stderr,"Assignment of print device: %s failed.",output);
  107.         exit(1);
  108.         }
  109.     fd=fopen(fname,"r");    /*open program file to list*/
  110.     if (fd==NULL) {
  111.         fprintf(stderr,"Cannot Open File: %s \n",fname);
  112.         exit(1);    /*error exit*/
  113.         }
  114.     linect = pagect = 1;    /*set page & line count to one*/
  115.     stmnt = j = rbrack = lbrack = rbrace = lbrace = rparen = lparen = 0;
  116.     callreg.bx =*fd;    /*get file handle*/
  117.     callreg.ax = 0x5700 ; /*get file data  */
  118.     sysint21(&callreg,&retreg);    /*fetch file date and time*/
  119.  
  120. /* n.b. -> ci86 c documentation is a bit confusing here.
  121.  the structure is naturally a memory area so it conflicts
  122.  in that sense with the register lo-hi multiplexing */
  123.  
  124.     month=(retreg.dx & 0x01E0)>>5;
  125.     day=retreg.dx & 0x001F;
  126.     year=((retreg.dx >>9)& 0x00EF)+80;
  127.     hour=(retreg.cx >>11) & 0x001F;
  128.     minute=(retreg.cx & 0x07E0)>>5;
  129.     second=(retreg.cx & 0x001F)<<1;    /* multiply by 2 */ 
  130.     strcpy(title,fname);
  131.     comment=squote=instrng=quote=FALSE;
  132.     toppage(prn);    /*take top of page action*/
  133.     while(fgets(lineimage,519,fd)!=NULL){
  134.         jj=strlen(lineimage);
  135.         for(i=0;k=lineimage[i],k!='\0'&& i<jj;i++){
  136.             kk=k;
  137.             if (kk=='\n')
  138.                 {
  139.                 lines++;
  140.                 }
  141.             if (comment==FALSE && instrng==FALSE) {
  142. /* switch is entered when processing outside a comment
  143. or string.  If in a comment or string (either " or ') then
  144. the if statement drops thru to the else at the
  145. conclusion of the loop to turn processing back on
  146. In the case of alphanumerics the loop is totally ignored.
  147. */
  148.                 if (isalnum(k)==0){ /* don't switch on alphanumerics */
  149.                 switch (kk)    {
  150.             case '{':
  151.                 level++;
  152.                 lbrace++;
  153.                 break;
  154.             case '}':
  155.                 rbrace++;
  156.                 level--;
  157.                 break;
  158.             case '(':
  159.                 lparen++;
  160.                 break;
  161.             case ')':
  162.                 rparen++;
  163.                 break;
  164.             case '[':
  165.                 lbrack++;
  166.                 break;
  167.             case ']':
  168.                 rbrack++;
  169.                 break;
  170.             case '/':
  171.                 comment= lineimage[i+1]=='*';
  172.                 break;
  173.             case ';':
  174.                 stmnt++;
  175.                 break;
  176.             case '\'':
  177.                 quote=!squote;
  178.                 instrng=quote|squote;
  179.                 break;
  180.             case '"':
  181.                 squote= !quote;
  182.                 instrng= squote|quote;
  183.                 break;
  184.                     }
  185.                 }
  186.             }
  187.             else { /*if comment or instrng == TRUE*/
  188.                 if (comment==TRUE && k=='*' && lineimage[i+1]=='/')
  189.                     comment=FALSE;
  190.                 if (quote==TRUE && k=='\'' &&
  191.                 (lineimage[i-1] != '\\' ||
  192.                 (lineimage[i-2]=='\\' && lineimage[i-1]=='\\')))
  193.                     quote=FALSE;
  194.                 if (squote==TRUE && k=='"') squote=FALSE;
  195.                 instrng = quote | squote;
  196.             }
  197.         if (k=='\t') for(n=j;buf[j++]=' ',j<n+TAB;);
  198.         else buf[j++]=k;
  199.         if (j>CHPL || k == '\n'){
  200.             if (k != '\n') 
  201.                 buf[j++]='\n';
  202.             buf[j]='\0';
  203.             fprintf(prn,"%2d%4d: %s",level,lines,buf);
  204.             j=0;
  205.             if (linect++>LPP) toppage(prn);
  206.             }
  207.         }
  208.     }
  209. fclose(fd);
  210. if (level==0 && rbrack==lbrack && rparen==lparen)
  211.     {
  212.     fprintf(prn,"\n%d Statements in source code.  \
  213. Braces, brackets and parenthesis are balanced.\n",stmnt);
  214.     }
  215. else
  216.     {
  217.     fprintf(prn,"\nUnbalanced pairs { %d, } %d, [ %d, ] %d, ( %d, ) %d\n",
  218.     lbrace,rbrace,lbrack,rbrack,lparen,rparen);
  219. fclose(prn);
  220.     }
  221. }
  222.